from abc import ABC

from rest_framework import serializers

from config.redisconfig import LOGIN_VERIFY_CODE_TEMPLATE
from django_redis import get_redis_connection
from django.contrib.auth.models import User
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework_simplejwt.serializers import TokenObtainSlidingSerializer
from user.models import UserDetail


# 用户详情展示表
class UserDetailSerializer(ModelSerializer):
    class Meta:
        model = UserDetail
        fields = '__all__'

        extra_kwargs = {
            'user': {'write_only': True},
            'avatar': {'read_only': True}  # 以后要单独写接口去实现头像操作
        }


# 对应school的序列化文件，当User表是别人已写好时，我们需要定义user表的序列化器
class UserSerializer(ModelSerializer):
    userdetail = UserDetailSerializer(required=False, read_only=True)  # 不一定有详情, 只读

    class Meta:
        model = User
        exclude = ['password', 'last_name', 'user_permissions']  # 排除字段

        extra_kwargs = {  # 对已有的字段进行修改
            'last_login': {'read_only': True},  # 上次登录日期
            'is_superuser': {'read_only': True},  # 是否为超级用户
            'is_staff': {'read_only': True},  # 是否为工作人员状态
            'is_active': {'read_only': True},  # 是否为有效用户
            'date_joined': {'read_only': True},  # 加入日期
            'groups': {'read_only': True},  # 用户所在的组
        }


# 优化JWT返回的token数据，重写token序列化
class MyTokenSerializer(TokenObtainSlidingSerializer):
    def validate(self, attrs):  # 校验数据
        data = super().validate(attrs)  # 继承父类的校验,data就是返回的token
        data['id'] = self.user.id
        data['username'] = self.user.username
        data['avatar'] = self.user.userdetail.avatar if hasattr(self.user, 'userdetail') else None  # 三目运算

        # 图形验证码的校验
        # 1.拿到验证码的键和值
        uuid = self.initial_data.get('uuid')
        verify = self.initial_data.get('verify')
        if not uuid or not verify:
            return {'msg': '请输入验证码'}

        # 2.获取数据库缓存的验证码
        cache = get_redis_connection(alias='verify_codes')
        redis_verify = cache.get(LOGIN_VERIFY_CODE_TEMPLATE % uuid)
        cache.delete(LOGIN_VERIFY_CODE_TEMPLATE % uuid)  # 及时清除释放拿到的缓存验证码
        if not redis_verify:
            return {'msg': '验证码已过期'}

        # 3.如果没过期，就比较两个码是否一致
        if redis_verify.lower() != verify.lower():
            return {'msg': '验证码错误'}

        return data


class CreateUserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'first_name', 'email']
        extra_kwargs = {    # 对确定已有的字段进行修改
            'first_name': {
                'required': True,  # 必填
            },
            'email': {
                'required': True,
            },
        }


class UpdatePasswordSerializer(Serializer):
    password = serializers.CharField(max_length=70, label='旧密码')
    new_password = serializers.CharField(max_length=70, label='新密码')
    repeat_password = serializers.CharField(max_length=70, label='确认密码')

    # 自定义校验新密码和确认密码字段,全字段校验
    def validate(self, attrs):  # 所有的密码都放在attr里面
        if attrs['new_password'] != attrs['repeat_password']:
            raise serializers.ValidationError('两次输入的密码不一致')
        return attrs